package cn.modoumama.common.tools;

import java.math.BigDecimal;

/**
 * 常用数学公式<br>
 *
 * 创建人：邓强   <br>
 * 创建时间：2018/5/3/003 17:13    <br>
 * @version   V1.0
 */
public class MathTool {

	/**
	 * 保留单精度小数位个数
	 * @param value  需要修改的值
     * @param number  保留小数位个数
	 * @return  返回保留小数位之后的值
	 */
	public static BigDecimal decimal(Number value, int number){
		BigDecimal bd =  getBigDecimal(value);
		bd = bd.setScale(number, BigDecimal.ROUND_HALF_UP);
		return bd;
	}
	
	/**
	 * @Title: toInt  
	 * @Description: 转整形
	 * @param value
	 * @return
	 */
	public static int toInt(Number value){
		return value.intValue();
	}

    /**
     * 加法运算(d1+d2)
     *
     * @param d1
     * @param d2
     * @return double
     */
    public static double add(Number d1, Number d2) { // 进行加法运算
        BigDecimal b1 = getBigDecimal(d1.doubleValue());
        BigDecimal b2 = getBigDecimal(d2.doubleValue());
        return b1.add(b2).doubleValue();
    }


    /**
     * 减法运算(d1-d2)
     *
     * @param d1
     * @param d2
     * @return double
     */
    public static double sub(Number d1, Number d2) { // 进行减法运算
        BigDecimal b1 = getBigDecimal(d1.doubleValue());
        BigDecimal b2 = getBigDecimal(d2.doubleValue());
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 乘法运算(d1*d2)
     *
     * @param d1
     * @param d2
     * @return double
     */
    public static BigDecimal mul(Number d1, Number d2) { // 进行乘法运算
        BigDecimal b1 = getBigDecimal(d1.doubleValue());
        BigDecimal b2 = getBigDecimal(d2.doubleValue());
        return b1.multiply(b2);
    }

    /**
     *  除法运算(d1/d2)
     * @param d1
     * @param d2
     * @return
     */
    public static BigDecimal div(Number d1, Number d2) {// 进行除法运算
        return div(d1, d2, 2);
    }

    /**
     * 除法运算(d1/d2)
     *
     * @param d1
     * @param d2
     * @param len   指定结果的精度，默认小数点后2位
     * @return double
     */
    public static BigDecimal div(Number d1, Number d2, int len) {
        BigDecimal b1 = getBigDecimal(d1.doubleValue());
        BigDecimal b2 = getBigDecimal(d2.doubleValue());
        return b1.divide(b2, len, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 始终对非舍弃部分前面的数字加1<br>
     * 0.1203456789,当精度为3的时候，按照round_up模式，结果是0.121<br>
     * -0.1203456789,当精度为3的时候，按照round_up模式，结果是-0.121<br>
     *
     * @param number
     * @param len
     * @return
     */
    public static BigDecimal roundUp(Number number, int len) {
        BigDecimal bigDecimal = getBigDecimal(number);
        return   bigDecimal.setScale(len, BigDecimal.ROUND_UP);
    }

    /**
     * 从不对舍弃部分前面的数字加1<br>
     * 0.1203456789,当精度为3的时候，按照round_down模式，结果是0.12，自动去掉了2后面的0<br>
     * -0.1203456789,当精度为3的时候，按照round_down模式，结果是-0.12，自动去掉了2后面的0<br>
     *
     * @param number
     * @param len
     * @return
     */
    public static BigDecimal roundDown(Number number, int len) {
        BigDecimal bigDecimal = getBigDecimal(number);
        return   bigDecimal.setScale(len, BigDecimal.ROUND_DOWN);
    }

    /**
     * 接近正无穷大的舍入模式<br>
     *如果 BigDecimal 为正，则舍入行为与 ROUND_UP 相同;<br>
     * 如果为负，则舍入行为与 ROUND_DOWN 相同。<br>
     * 注意，此舍入模式始终不会减少计算值。<br>
     *
     * @param number
     * @param len
     * @return
     */
    public static BigDecimal roundCeiling(Number number, int len) {
        BigDecimal bigDecimal = getBigDecimal(number);
        return   bigDecimal.setScale(len, BigDecimal.ROUND_CEILING);
    }

    /**
     * 接近负无穷大的舍入模式。<br>
     * 如果 BigDecimal 为正，则舍入行为与 ROUND_DOWN 相同;<br>
     * 如果为负，则舍入行为与 ROUND_UP 相同。<br>
     * 注意，此舍入模式始终不会增加计算值。<br>
     *
     * @param number
     * @param len
     * @return
     */
    public static BigDecimal roundFloor(Number number, int len) {
        BigDecimal bigDecimal = getBigDecimal(number);
        return   bigDecimal.setScale(len, BigDecimal.ROUND_FLOOR);
    }

    /**
     * 向“最接近的”数字舍入，如果与两个相邻数字的距离相等，则为向上舍入的舍入模式。<br>
     * 如果舍弃部分 >= 0.5，则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。<br>
     * 注意，这是我们大多数人在小学时就学过的舍入模式(四舍五入)。<br>
     *
     *
     * @param number
     * @param len
     * @return
     */
    public static BigDecimal roundHalf_up(Number number, int len) {
        BigDecimal bigDecimal = getBigDecimal(number);
        return   bigDecimal.setScale(len, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 向“最接近的”数字舍入，如果与两个相邻数字的距离相等，则为上舍入的舍入模式。<br>
     * 如果舍弃部分 > 0.5，则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。<br>
     *
     * @param number
     * @param len
     * @return
     */
    public static BigDecimal roundHalfDown(Number number, int len) {
        BigDecimal bigDecimal = getBigDecimal(number);
        return   bigDecimal.setScale(len, BigDecimal.ROUND_HALF_DOWN);
    }

    /**
     * 向“最接近的”数字舍入，如果与两个相邻数字的距离相等，则向相邻的偶数舍入。<br>
     * 如果舍弃部分左边的数字为奇数，则舍入行为与 ROUND_HALF_UP 相同;<br>
     * 如果为偶数，则舍入行为与 ROUND_HALF_DOWN 相同。<br>
     * 注意，在重复进行一系列计算时，此舍入模式可以将累加错误减到最小。<br>
     *
     * @param number
     * @param len
     * @return
     */
    public static BigDecimal roundHalfEven(Number number, int len) {
        BigDecimal bigDecimal = getBigDecimal(number);
        return   bigDecimal.setScale(len, BigDecimal.ROUND_HALF_EVEN);
    }

    /**
     * 断言请求的操作具有精确的结果，因此不需要舍入。<br>
     * 如果对获得精确结果的操作指定此舍入模式，则抛出ArithmeticException。<br>
     *
     * @param number
     * @param len
     * @return
     */
    public static BigDecimal roundUnnecessary(Number number, int len) {
        BigDecimal bigDecimal = getBigDecimal(number);
        return   bigDecimal.setScale(len, BigDecimal.ROUND_UNNECESSARY);
    }

	/**
	 * 数据转换为BigDecimal
	 * @param number
	 * @return
	 */
	public static BigDecimal getBigDecimal(Number number){
        if (number instanceof BigDecimal) {
            return (BigDecimal) number;
        } else {
            return BigDecimal.valueOf(number.doubleValue());
        }
    }
}
